﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Xml;


public class MessageHandlerBuilder
{
    #region public constant
    public const string CPP_ROOT = ".\\cpp";
    public const string CSHARP_ROOT = ".\\csharp";
    public const string TAB = "Tab";
    #endregion

    /*************************************************************************************************************/
    private static bool CheckCpp(string path)
    {
        return System.IO.File.Exists(CPP_ROOT + path + ".h");
    }

    private static bool CheckCSharp(string path)
    {
        return System.IO.File.Exists(CSHARP_ROOT + path + ".cs");
    }

    private static string GetMessagePath(TreeNode node)
    {
        StringBuilder path = new StringBuilder();
        TreeNode parent = node.Parent;

        while (parent != null)
        {
            path.Append(string.Format("\\{0}", parent.Text));
            parent = parent.Parent;
        }

        return path.ToString();
    }

    private static bool CheckProc(string type, TreeNode node)
    {
        string file_name = string.Format("{0}\\{1}\\{2}{3}", GetMessagePath(node), type, node.Text, type);

        return CheckCpp(file_name) && CheckCSharp(file_name);
    }

    private const string SENDER_TYPE = "Sender";
    private const string RECVIEVER_TYPE = "Reciever";
    public static bool CheckSender(TreeNode node)
    {
        return CheckProc(SENDER_TYPE, node);
    }

    public static bool CheckRecviever(TreeNode node)
    {
        return CheckProc(RECVIEVER_TYPE, node);
    }

    private static void RenameCpp(string file_name, string new_file_name)
    {
        file_name = CPP_ROOT + file_name + ".h";
        new_file_name = CPP_ROOT + new_file_name + ".h";
        if (System.IO.File.Exists(file_name))
        {
            System.IO.FileInfo fi = new System.IO.FileInfo(file_name);
            fi.MoveTo(new_file_name);
        }
    }

    private static void RenameCSharp(string file_name, string new_file_name)
    {
        file_name = CSHARP_ROOT + file_name + ".cs";
        new_file_name = CSHARP_ROOT + new_file_name + ".cs";
        if (System.IO.File.Exists(file_name))
        {
            System.IO.FileInfo fi = new System.IO.FileInfo(file_name);
            fi.MoveTo(new_file_name);
        }
    }

    private static void RenameCallback(string type, TreeNode node, string new_name)
    {
        string file_name = string.Format("{0}\\{1}\\{2}{3}", GetMessagePath(node), type, node.Text, type);
        string new_file_name = string.Format("{0}\\{1}\\{2}{3}", GetMessagePath(node), type, new_name, type);

        RenameCpp(file_name, new_file_name);
        RenameCSharp(file_name, new_file_name);
    }

    private static void RenameInCppFile(string file_name, string old_name, string new_name)
    {
        file_name = CPP_ROOT + file_name + ".h";
        string content = string.Empty;
        using (System.IO.FileStream file = new System.IO.FileStream(file_name, System.IO.FileMode.Open))
        {
            using (System.IO.StreamReader Reader = new System.IO.StreamReader(file))
            {
                content = Reader.ReadToEnd();
            }
        }

        content = content.Replace(old_name, new_name);

        using (System.IO.FileStream file = new System.IO.FileStream(file_name, System.IO.FileMode.Create))
        {
            using (System.IO.StreamWriter Writer = new System.IO.StreamWriter(file))
            {
                Writer.Write(content);
            }
        }
    }

    private static void RenameInCSharpFile(string file_name, string old_name, string new_name)
    {
        file_name = CSHARP_ROOT + file_name + ".cs";
        string content = string.Empty;
        using (System.IO.FileStream file = new System.IO.FileStream(file_name, System.IO.FileMode.Open))
        {
            using (System.IO.StreamReader Reader = new System.IO.StreamReader(file))
            {
                content = Reader.ReadToEnd();
            }
        }

        content = content.Replace(old_name, new_name);

        using (System.IO.FileStream file = new System.IO.FileStream(file_name, System.IO.FileMode.Create))
        {
            using (System.IO.StreamWriter Writer = new System.IO.StreamWriter(file))
            {
                Writer.Write(content);
            }
        }
    }

    private static void RenameInFile(string type, TreeNode node, string new_name)
    {
        string file_name = string.Format("{0}\\{1}\\{2}{3}", GetMessagePath(node), type, new_name, type);
        RenameInCppFile(file_name, node.Text, new_name);
        RenameInCSharpFile(file_name, node.Text, new_name);
    }

    public static void RenameCallback(TreeNode node, string new_name)
    {
        if (CheckSender(node))
        {
            RenameCallback(SENDER_TYPE, node, new_name);
            RenameInFile(SENDER_TYPE, node, new_name);
        }

        if (CheckRecviever(node))
        {
            RenameCallback(RECVIEVER_TYPE, node, new_name);
            RenameInFile(RECVIEVER_TYPE, node, new_name);
        }
    }

    /*************************************************************************************************************/

    private static void GenerateCppSender(System.IO.StreamWriter writer, string msg_name, string msg_header, string param_name, bool main_msg)
    {
        string header_name = msg_name + SENDER_TYPE;
        StringBuilder content = new StringBuilder();
        content.Append(string.Format("#ifndef __{0}_H__\r\n", header_name.ToUpper()));
        content.Append(string.Format("#define __{0}_H__\r\n", header_name.ToUpper()));
        content.Append("\r\n");
        content.Append("#include \"gwmessagemap.hpp\"\r\n");
        content.Append("#include \"IMessageOperator.h\"\r\n");
        content.Append("#include \"protonet.hpp\"\r\n");
        content.Append("#include \"netlib.h\"\r\n");
        content.Append(string.Format("#include \"../{0}.h\"\r\n", msg_header));
        content.Append("\r\n");
        content.Append("/**\r\n");
        content.Append(string.Format("*@file       {0}.h\r\n", header_name));
        content.Append(string.Format("*@brief      send message {0}\r\n", msg_name));
        content.Append("*\r\n");
        content.Append("*@author     graywind\r\n");
        content.Append("*@version    1.0.0.0\r\n");
        System.DateTime dt = DateTime.Now;
        content.Append(string.Format("*@data       {0}/{1}/{2}\r\n", dt.Year, dt.Month, dt.Day));
        content.Append("*/\r\n\r\n");
        content.Append("///message wrapper\r\n");
        content.Append(string.Format("class msg{0}\r\n", msg_name));
        content.Append("{\r\n");
        content.Append("public:\r\n");
        content.Append(string.Format("    static const int MessageId = {0};\r\n", msg_name));
        content.Append("    //TODO\r\n");
        content.Append("};\r\n");
        content.Append("\r\n");
        content.Append(string.Format("class Handle{0}\r\n", msg_name));
        content.Append("{\r\n");
        content.Append("public:\r\n");
        if (param_name == string.Empty)
        {
            content.Append("    ///@brief     handle message\r\n");
            content.Append(string.Format("    ///param[in]  msg     message wrapper of {0}\r\n", msg_name));
            content.Append("    ///retval     void\r\n");
            content.Append(string.Format("    static void HandleMessage(msg{0}* msg)\r\n", msg_name));
        }
        else
        {
            content.Append("    ///@brief     handle message\r\n");
            content.Append(string.Format("    ///param[in]  msg     message wrapper of {0}\r\n", msg_name));
            content.Append(string.Format("    ///param[in]  param   user-defined parameter({0})\r\n", param_name));
            content.Append("    ///retval     void\r\n");
            content.Append(string.Format("    static void HandleMessage(msg{0}* msg, {1}* param)\r\n", msg_name, param_name));
        }
        content.Append("    {\r\n");
        content.Append("        //TODO\r\n");

        if(main_msg)
            content.Append(string.Format("        //Main Message:  msg{0}\r\n", msg_header));

        content.Append("    }\r\n");
        content.Append("};\r\n");
        if (param_name == string.Empty)
        {
            content.Append("///[message wrapper]  [handler]\r\n");
            content.Append(string.Format("RegisterHandler(msg{0}, Handle{1});\r\n", msg_name, msg_name));
        }
        else
        {
            content.Append("///[message wrapper]  [parameter]  [handler]\r\n");
            content.Append(string.Format("RegisterHandler(msg{0}, {1}, Handle{2});\r\n", msg_name, param_name, msg_name));
        }
        content.Append("\r\n");
        content.Append("#endif\r\n");

        writer.Write(content);
    }

    private static void GenerateCppSender(TreeNode node, string param_name)
    {
        StringBuilder path = new StringBuilder();
        TreeNode parent = node.Parent;

        while (parent != null)
        {
            path.Append(string.Format("\\{0}", parent.Text));
            parent = parent.Parent;
        }

        string msg_header = string.Empty;
        bool main_msg = false;
        if (node.Parent == null)
            msg_header = "NetMessage";
        else
        {
            msg_header = node.Parent.Text;
            main_msg = true;
        }


        string file_path = CPP_ROOT + string.Format("{0}\\Sender", path.ToString());

        if (System.IO.Directory.Exists(file_path) == false)
            System.IO.Directory.CreateDirectory(file_path);

        string file_name = string.Format("{0}\\{1}Sender.h", file_path, node.Text);

        using (System.IO.FileStream file = new System.IO.FileStream(file_name, System.IO.FileMode.Append))
        {
            using (System.IO.StreamWriter writer = new System.IO.StreamWriter(file))
            {
                GenerateCppSender(writer, node.Text, msg_header, param_name, main_msg);
            }
        }
    }

    private static void GenerateCSharpSender(System.IO.StreamWriter writer, string msg_name, string msg_header, string param_name, bool main_msg)
    {
        string header_name = msg_name + SENDER_TYPE;
        StringBuilder content = new StringBuilder();
        content.Append("using System;\r\n");
        content.Append("using System.Collections.Generic;\r\n");
        content.Append("using System.Text;\r\n");
        content.Append("using System.Runtime.InteropServices;\r\n");
        content.Append("\r\n");
        content.Append("/**\r\n");
        content.Append(string.Format("*@file       {0}.cs\r\n", header_name));
        content.Append(string.Format("*@brief      send message {0}\r\n", msg_name));
        content.Append("*\r\n");
        content.Append("*@author     graywind\r\n");
        content.Append("*@version    1.0.0.1\r\n");
        System.DateTime dt = DateTime.Now;
        content.Append(string.Format("*@data       {0}/{1}/{2}\r\n", dt.Year, dt.Month, dt.Day));
        content.Append("*/\r\n\r\n");
        content.Append(string.Format("//send message {0}\r\n", msg_name));
        content.Append(string.Format("public class msg{0}\r\n", msg_name));
        content.Append("{\r\n");
        content.Append(string.Format("    public const int MessageId = (int){0}Types.MessageType.{1};\r\n", msg_header, msg_name));
        content.Append("    //TODO\r\n");
        content.Append("}\r\n");
        content.Append("\r\n");
        content.Append("//handle message\r\n");
        content.Append("public partial class gwMessagePort\r\n");
        content.Append("{\r\n");
        if (param_name == string.Empty)
        {
            content.Append("    /// <summary>\r\n");
            content.Append("    /// handle message\r\n");
            content.Append("    /// </summary>\r\n");
            content.Append(string.Format("    /// <param name=\"msg\">message wrapper of {0}</param>\r\n", msg_name));
            content.Append(string.Format("    public static void ProcessMessage(msg{0} msg)\r\n", msg_name));
        }
        else
        {
            content.Append("    /// <summary>\r\n");
            content.Append("    /// handle message\r\n");
            content.Append("    /// </summary>\r\n");
            content.Append(string.Format("    /// <param name=\"msg\">message wrapper of {0}</param>\r\n", msg_name));
            content.Append(string.Format("    /// <param name=\"param\">user-defined parameter({0})</param>\r\n", param_name));
            content.Append(string.Format("    public static void ProcessMessage(msg{0} msg, {1} param)\r\n", msg_name, param_name));
        }

        content.Append("    {\r\n");
        content.Append("        //TODO\r\n");

        if (main_msg)
            content.Append(string.Format("        //Main Message:  msg{0}\r\n", msg_header));

        content.Append("    }\r\n");
        content.Append("}\r\n");

        writer.Write(content);
    }

    private static void GenerateCSharpSender(TreeNode node, string param_name)
    {
        StringBuilder path = new StringBuilder();
        TreeNode parent = node.Parent;

        while (parent != null)
        {
            path.Append(string.Format("\\{0}", parent.Text));
            parent = parent.Parent;
        }

        string msg_header = string.Empty;
        bool main_msg = false;
        if (node.Parent == null)
            msg_header = "NetMessage";
        else
        {
            msg_header = node.Parent.Text;
            main_msg = true;
        }

        string file_path = CSHARP_ROOT + string.Format("{0}\\Sender", path.ToString());

        if (System.IO.Directory.Exists(file_path) == false)
            System.IO.Directory.CreateDirectory(file_path);

        string file_name = string.Format("{0}\\{1}Sender.cs", file_path, node.Text);

        using (System.IO.FileStream file = new System.IO.FileStream(file_name, System.IO.FileMode.Append))
        {
            using (System.IO.StreamWriter writer = new System.IO.StreamWriter(file))
            {
                GenerateCSharpSender(writer, node.Text, msg_header, param_name, main_msg);
            }
        }
    }

    public static void GenerateSender(TreeNode node, string param_name)
    {
        GenerateCppSender(node, param_name);
        GenerateCSharpSender(node, param_name);
    }

    /************************************************************************************************************/

    private static void GenerateCppReciever(System.IO.StreamWriter writer, string msg_name, string msg_header)
    {
        string header_name = msg_name + RECVIEVER_TYPE;
        StringBuilder content = new StringBuilder();
        content.Append(string.Format("#ifndef __{0}_H__\r\n", header_name.ToUpper()));
        content.Append(string.Format("#define __{0}_H__\r\n", header_name.ToUpper()));
        content.Append("\r\n");
        content.Append("#include \"gwmessagetab.hpp\"\r\n");
        content.Append("#include \"IMessageOperator.h\"\r\n");
        content.Append("#include \"protonet.hpp\"\r\n");
        content.Append(string.Format("#include \"../{0}Tab.h\"\r\n", msg_header));
        content.Append("\r\n");
        content.Append("/**\r\n");
        content.Append(string.Format("*@file       {0}.h\r\n", header_name));
        content.Append(string.Format("*@brief      process message {0}\r\n", msg_name));
        content.Append("*\r\n");
        content.Append("*@author     graywind\r\n");
        content.Append("*@version    1.0.0.0\r\n");
        System.DateTime dt = DateTime.Now;
        content.Append(string.Format("*@data       {0}/{1}/{2}\r\n", dt.Year, dt.Month, dt.Day));
        content.Append("*/\r\n\r\n");
        content.Append("///process message\r\n");
        content.Append(string.Format("class On{0}\r\n", msg_name));
        content.Append("{\r\n");
        content.Append("public:\r\n");
        content.Append("    ///@brief    process message\r\n");
        content.Append("    ///param[in] op            operator type\r\n");
        content.Append("    ///param[in] session_id    identifier of session\r\n");
        content.Append("    ///param[in] pMsgBuffer    message buffer\r\n");
        content.Append("    ///param[in] msg_bytes     byte length of message buffer\r\n");
        content.Append("    ///retval    void\r\n");
        content.Append("    static void OnMapping(IMessageOperator* op, int session_id, void* pMsgBuffer, unsigned long msg_bytes)\r\n");
        content.Append("    {\r\n");
        content.Append("        //TODO\r\n");
        content.Append("    }\r\n");
        content.Append("};\r\n");
        content.Append("\r\n");
        content.Append("///[message group]  [message type]  [function table] [handler]\r\n");
        content.Append(string.Format("RegisterMessageTab({0}Types, {1}, {2}Tab, On{3});\r\n", msg_header, msg_name, msg_header, msg_name));
        content.Append("#endif\r\n");

        writer.Write(content);
    }

    private static void GenerateCppReciever(TreeNode node)
    {
        StringBuilder path = new StringBuilder();
        TreeNode parent = node.Parent;

        while (parent != null)
        {
            path.Append(string.Format("\\{0}", parent.Text));
            parent = parent.Parent;
        }

        string msg_header = string.Empty;
        if (node.Parent == null)
            msg_header = "NetMessage";
        else
            msg_header = node.Parent.Text;

        string file_path = CPP_ROOT + string.Format("{0}\\Reciever", path.ToString());

        if (System.IO.Directory.Exists(file_path) == false)
            System.IO.Directory.CreateDirectory(file_path);

        string file_name = string.Format("{0}\\{1}Reciever.h", file_path, node.Text);

        using (System.IO.FileStream file = new System.IO.FileStream(file_name, System.IO.FileMode.Append))
        {
            using (System.IO.StreamWriter writer = new System.IO.StreamWriter(file))
            {
                GenerateCppReciever(writer, node.Text, msg_header);
            }
        }
    }

    private static void GenerateCSharpReciever(System.IO.StreamWriter writer, string msg_name, string msg_header)
    {
        string header_name = msg_name + RECVIEVER_TYPE;
        StringBuilder content = new StringBuilder();
        content.Append("using System;\r\n");
        content.Append("using System.Collections.Generic;\r\n");
        content.Append("using System.Text;\r\n");
        content.Append("using System.Runtime.InteropServices;\r\n");
        content.Append("\r\n");
        content.Append("/**\r\n");
        content.Append(string.Format("*@file       {0}.cs\r\n", header_name));
        content.Append(string.Format("*@brief      process message {0}\r\n", msg_name));
        content.Append("*\r\n");
        content.Append("*@author     graywind\r\n");
        content.Append("*@version    1.0.0.1\r\n");
        System.DateTime dt = DateTime.Now;
        content.Append(string.Format("*@data       {0}/{1}/{2}\r\n", dt.Year, dt.Month, dt.Day));
        content.Append("*/\r\n\r\n");
        content.Append(string.Format("//process {0}\r\n", msg_name));
        content.Append(string.Format("public class On{0}\r\n", msg_name));
        content.Append("{\r\n");
        content.Append("    /// <summary>\r\n    /// process message\r\n    /// </summary>\r\n    /// <param name=\"op\">message operator</param>\r\n    /// <param name=\"session_id\">session identifier</param>\r\n");
        content.Append("    /// <param name=\"msg_buffer\">message buffer</param>\r\n    /// <param name=\"msg_bytes\">buffer length</param>\r\n");
        content.Append("    public static void OnMapping(IMessageOperator op, Int32 session_id, byte[] msg_buffer, UInt32 msg_bytes)\r\n");
        content.Append("    {\r\n");
        content.Append("        //TODO\r\n");
        content.Append("    }\r\n");
        content.Append("}\r\n");
        content.Append("\r\n");
        content.Append("//register callback\r\n");
        content.Append("partial class MessageProcTypes<ProcType, MessageProc>\r\n");
        content.Append("{\r\n");
        content.Append(string.Format("        [MessageProcType((int){0}Types.MessageType.{1})]\r\n", msg_header, msg_name));
        content.Append(string.Format("        public static {0}Processor.{1}Func {2}Proc = new {3}Processor.{4}Func(On{5}.OnMapping);\r\n", msg_header, msg_header + TAB, msg_name, msg_header, msg_header + TAB, msg_name));
        content.Append("}\r\n");

        writer.Write(content);
    }

    private static void GenerateCSharpReciever(TreeNode node)
    {
        StringBuilder path = new StringBuilder();
        TreeNode parent = node.Parent;

        while (parent != null)
        {
            path.Append(string.Format("\\{0}", parent.Text));
            parent = parent.Parent;
        }

        string msg_header = string.Empty;
        if (node.Parent == null)
            msg_header = "NetMessage";
        else
            msg_header = node.Parent.Text;

        string file_path = CSHARP_ROOT + string.Format("{0}\\Reciever", path.ToString());

        if (System.IO.Directory.Exists(file_path) == false)
            System.IO.Directory.CreateDirectory(file_path);

        string file_name = string.Format("{0}\\{1}Reciever.cs", file_path, node.Text);

        using (System.IO.FileStream file = new System.IO.FileStream(file_name, System.IO.FileMode.Append))
        {
            using (System.IO.StreamWriter writer = new System.IO.StreamWriter(file))
            {
                GenerateCSharpReciever(writer, node.Text, msg_header);
            }
        }
    }

    public static void GenerateReciever(TreeNode node)
    {
        GenerateCppReciever(node);
        GenerateCSharpReciever(node);
    }

    /*************************************************************************************************************/
    private static void CPPMessageTypesWriter(System.IO.StreamWriter writer, string header_name, TreeNodeCollection collection)
    {
        StringBuilder content = new StringBuilder();
        content.Append(string.Format("#ifndef __{0}_H__\r\n", header_name.ToUpper()));
        content.Append(string.Format("#define __{0}_H__\r\n", header_name.ToUpper()));
        content.Append("\r\n");
        content.Append("/**\r\n");
        content.Append(string.Format("*@file       {0}.h\r\n", header_name));
        content.Append("*@brief      network message type\r\n");
        content.Append("*\r\n");
        content.Append("*@author     graywind\r\n");
        content.Append("*@version    1.0.0.1\r\n");
        System.DateTime dt = DateTime.Now;
        content.Append(string.Format("*@data       {0}/{1}/{2}\r\n", dt.Year, dt.Month, dt.Day));
        content.Append("*/\r\n\r\n");
        content.Append("///all message types\r\n");
        content.Append(string.Format("enum {0}Types\r\n", header_name));
        content.Append("{\r\n");

        foreach (TreeNode node in collection)
        {
            content.Append(string.Format("    {0},\r\n", node.Text));
        }

        content.Append(string.Format("    MAX_{0}_TYPES\r\n", header_name.ToUpper()));
        content.Append("};\r\n");
        content.Append("#endif\r\n");

        writer.Write(content);
    }

    private static void GernerateCPPMessageTab(System.IO.StreamWriter writer, string node_name)
    {
        string header_name = node_name + TAB;
        StringBuilder content = new StringBuilder();
        content.Append(string.Format("#ifndef __{0}_H__\r\n", header_name.ToUpper()));
        content.Append(string.Format("#define __{0}_H__\r\n", header_name.ToUpper()));
        content.Append("\r\n");
        content.Append(string.Format("#include \"{0}.h\"\r\n", node_name));
        content.Append("#include \"gwmessagetab.hpp\"\r\n");
        content.Append("#include \"IMessageOperator.h\"\r\n");
        content.Append("\r\n");
        content.Append("/**\r\n");
        content.Append(string.Format("*@file       {0}.h\r\n", header_name));
        content.Append("*@brief      process message\r\n");
        content.Append("*\r\n");
        content.Append("*@author     graywind\r\n");
        content.Append("*@version    1.0.0.0\r\n");
        System.DateTime dt = DateTime.Now;
        content.Append(string.Format("*@data       {0}/{1}/{2}\r\n", dt.Year, dt.Month, dt.Day));
        content.Append("*/\r\n\r\n");
        content.Append("///define pointer of function\r\n");
        content.Append(string.Format("typedef void(*{0}Func)(IMessageOperator* op, int session_id, void* pMsgBuffer, unsigned long msg_bytes);\r\n", header_name));
        content.Append("////define message tab\r\n");
        content.Append(string.Format("typedef gwMessageTab<{0}Types, MAX_{1}_TYPES, {2}Func>   {3};\r\n", node_name, node_name.ToUpper(), header_name, header_name));
        content.Append("////process message\r\n");
        content.Append(string.Format("class {0}Processor\r\n", node_name));
        content.Append("{\r\n");
        content.Append("public:\r\n");
        content.Append("    ///@brief    process message\r\n");
        content.Append("    ///param[in] op            operator type\r\n");
        content.Append("    ///param[in] session_id    identifier of session\r\n");
        content.Append("    ///param[in] pMsgBuffer    message buffer\r\n");
        content.Append("    ///param[in] msgID         identifier of this message\r\n");
        content.Append("    ///param[in] msg_bytes     byte length of message buffer\r\n");
        content.Append("    ///retval    void\r\n");
        content.Append("    static void ProcessMessage(IMessageOperator* op, int session_id, void* pMsgBuffer, unsigned long msgID, unsigned long msg_bytes)\r\n");
        content.Append("    {\r\n");
        content.Append(string.Format("        {0}::FuncPtrArray[msgID](op, session_id, pMsgBuffer, msg_bytes);\r\n", header_name));
        content.Append("    }\r\n");
        content.Append("};\r\n");
        content.Append("#endif\r\n");

        writer.Write(content);
    }

    private static void GenerateCPPMessageTypes(TreeNode parent, string parent_path)
    {
        if (parent.Nodes.Count > 0)
        {
            string path = string.Format("{0}\\{1}", parent_path, parent.Text);
            if (System.IO.Directory.Exists(path) == false)
                System.IO.Directory.CreateDirectory(path);

            foreach (TreeNode node in parent.Nodes)
            {
                using (System.IO.FileStream file = new System.IO.FileStream(string.Format("{0}\\{1}.h", path, parent.Text), System.IO.FileMode.Create))
                {
                    using (System.IO.StreamWriter writer = new System.IO.StreamWriter(file))
                    {
                        CPPMessageTypesWriter(writer, parent.Text, parent.Nodes);
                    }
                }

                GenerateCPPMessageTypes(node, path);
            }

            using (System.IO.FileStream file = new System.IO.FileStream(string.Format("{0}\\{1}Tab.h", path, parent.Text), System.IO.FileMode.Create))
            {
                using (System.IO.StreamWriter writer = new System.IO.StreamWriter(file))
                {
                    GernerateCPPMessageTab(writer, parent.Text);
                }
            }
        }
    }

    private static void GenerateCPPMessageTypes(TreeNodeCollection Nodes)
    {
        using (System.IO.FileStream file = new System.IO.FileStream(string.Format("{0}\\NetMessage.h", CPP_ROOT), System.IO.FileMode.Create))
        {
            using (System.IO.StreamWriter writer = new System.IO.StreamWriter(file))
            {
                CPPMessageTypesWriter(writer, "NetMessage", Nodes);
            }
        }

        using (System.IO.FileStream file = new System.IO.FileStream(string.Format("{0}\\NetMessageTab.h", CPP_ROOT), System.IO.FileMode.Create))
        {
            using (System.IO.StreamWriter writer = new System.IO.StreamWriter(file))
            {
                GernerateCPPMessageTab(writer, "NetMessage");
            }
        }

        foreach (TreeNode node in Nodes)
        {
            GenerateCPPMessageTypes(node, CPP_ROOT);
        }
    }

    private static void CSharpMessageTypesWriter(System.IO.StreamWriter writer, string source_name, TreeNodeCollection collection)
    {
        StringBuilder content = new StringBuilder();
        content.Append("using System;\r\n");
        content.Append("using System.Collections.Generic;\r\n");
        content.Append("using System.Text;\r\n");
        content.Append("\r\n");
        content.Append("/**\r\n");
        content.Append(string.Format("*@file       {0}.cs\r\n", source_name));
        content.Append("*@brief      network message type\r\n");
        content.Append("*\r\n");
        content.Append("*@author     graywind\r\n");
        content.Append("*@version    1.0.0.1\r\n");
        System.DateTime dt = DateTime.Now;
        content.Append(string.Format("*@data       {0}/{1}/{2}\r\n", dt.Year, dt.Month, dt.Day));
        content.Append("*/\r\n\r\n");
        content.Append(string.Format("public class {0}Types : IGetMaxTypeCount\r\n", source_name));
        content.Append("{\r\n");
        content.Append("    ///all message types\r\n");
        content.Append("    public enum MessageType\r\n");
        content.Append("    {\r\n");


        foreach (TreeNode node in collection)
        {
            content.Append(string.Format("        {0},\r\n", node.Text));
        }

        content.Append("        ALL_TYPES\r\n");
        content.Append("    }\r\n");
        content.Append("\r\n\r\n");
        content.Append("    public int GetMaxTypeCount()\r\n");
        content.Append("    {\r\n");
        content.Append(string.Format("        return (int)MessageType.ALL_TYPES;\r\n", source_name));
        content.Append("    }\r\n");
        content.Append("}\r\n");

        writer.Write(content);
    }

    private static void GenerateCSharpMessageTab(System.IO.StreamWriter writer, string node_name)
    {
        string header_name = node_name + TAB;
        StringBuilder content = new StringBuilder();
        content.Append("using System;\r\n");
        content.Append("using System.Collections.Generic;\r\n");
        content.Append("using System.Text;\r\n");
        content.Append("\r\n");
        content.Append("/**\r\n");
        content.Append(string.Format("*@file       {0}.cs\r\n", header_name));
        content.Append("*@brief      process message\r\n");
        content.Append("*\r\n");
        content.Append("*@author     graywind\r\n");
        content.Append("*@version    1.0.0.1\r\n");
        System.DateTime dt = DateTime.Now;
        content.Append(string.Format("*@data       {0}/{1}/{2}\r\n", dt.Year, dt.Month, dt.Day));
        content.Append("*/\r\n\r\n");
        content.Append("//process message\r\n");
        content.Append(string.Format("public class {0}Processor\r\n", node_name));
        content.Append("{\r\n");
        content.Append(string.Format("    public delegate void {0}Func(IMessageOperator op, Int32 session_id, byte[] msg_buffer, UInt32 msg_bytes);\r\n\r\n", header_name));
        content.Append("    /// <summary>\r\n/// process message\r\n    /// </summary>\r\n    /// <param name=\"op\">message operator</param>\r\n    /// <param name=\"session_id\">session identifier</param>\r\n");
        content.Append("    /// <param name=\"msg_id\">message identifier</param>\r\n    /// <param name=\"msg_buffer\">message buffer</param>\r\n    /// <param name=\"msg_bytes\">buffer length</param>\r\n");
        content.Append("    public static void ProcessMessage(IMessageOperator op, Int32 session_id, UInt32 msg_id, byte[] msg_buffer, UInt32 msg_bytes)\r\n");
        content.Append("    {\r\n");
        content.Append(string.Format("        gwMessageTab<{0}Types, {1}Func>.FuncPtrArray[msg_id](op, session_id, msg_buffer, msg_bytes);\r\n", node_name, header_name));
        content.Append("    }\r\n");
        content.Append("}\r\n");

        writer.Write(content);
    }

    private static void GenerateCSharpMessageTypes(TreeNode parent, string parent_path)
    {
        if (parent.Nodes.Count > 0)
        {
            string path = string.Format("{0}\\{1}", parent_path, parent.Text);
            if (System.IO.Directory.Exists(path) == false)
                System.IO.Directory.CreateDirectory(path);

            foreach (TreeNode node in parent.Nodes)
            {
                using (System.IO.FileStream file = new System.IO.FileStream(string.Format("{0}\\{1}.cs", path, parent.Text), System.IO.FileMode.Create))
                {
                    using (System.IO.StreamWriter writer = new System.IO.StreamWriter(file))
                    {
                        CSharpMessageTypesWriter(writer, parent.Text, parent.Nodes);
                    }
                }

                GenerateCSharpMessageTypes(node, path);
            }

            using (System.IO.FileStream file = new System.IO.FileStream(string.Format("{0}\\{1}Tab.cs", path, parent.Text), System.IO.FileMode.Create))
            {
                using (System.IO.StreamWriter writer = new System.IO.StreamWriter(file))
                {
                    GenerateCSharpMessageTab(writer, parent.Text);
                }
            }
        }
    }

    private static void GenerateCSharpMessageTypes(TreeNodeCollection Nodes)
    {
        using (System.IO.FileStream file = new System.IO.FileStream(string.Format("{0}\\netmessage.cs", CSHARP_ROOT), System.IO.FileMode.Create))
        {
            using (System.IO.StreamWriter writer = new System.IO.StreamWriter(file))
            {
                CSharpMessageTypesWriter(writer, "NetMessage", Nodes);
            }
        }

        using (System.IO.FileStream file = new System.IO.FileStream(string.Format("{0}\\netmessagetab.cs", CSHARP_ROOT), System.IO.FileMode.Create))
        {
            using (System.IO.StreamWriter writer = new System.IO.StreamWriter(file))
            {
                GenerateCSharpMessageTab(writer, "NetMessage");
            }
        }

        foreach (TreeNode node in Nodes)
        {
            GenerateCSharpMessageTypes(node, CSHARP_ROOT);
        }
    }

    public static void GenerateMessageTypes(TreeNodeCollection Nodes)
    {
        if (System.IO.Directory.Exists(CPP_ROOT) == false)
            System.IO.Directory.CreateDirectory(CPP_ROOT);

        GenerateCPPMessageTypes(Nodes);

        if (System.IO.Directory.Exists(CSHARP_ROOT) == false)
            System.IO.Directory.CreateDirectory(CSHARP_ROOT);

        GenerateCSharpMessageTypes(Nodes);
    }
}